%macro FUNCTION 1
global _%1
_%1:
 .begin:
%endmacro


; int32 Atomic_Add( vint32 * value, int32 add )
FUNCTION Atomic_Add
	mov		edx, [esp + 4]				; edx = value
	mov		eax, [esp + 8]				; eax = add
	lock
	xadd	[edx], eax					; temp = eax + *edx, eax = *edx, *edx = temp
	ret									; return eax ( old edx )


; int32 Atomic_And( vint32 * value, int32 bits )
FUNCTION Atomic_And
	mov		edx, [esp + 4]				; edx = value
	mov		ecx, [esp + 8]				; ecx = bits
	mov		eax, [edx]					; eax = *edx
	and		ecx, eax					; ecx = ecx & eax
	lock
	cmpxchg	edx, ecx					; if( eax == *edx ) *edx = ecx
										; loop if the value was changed by another cpu
	jnz		.begin						; else goto .begin
	ret									; return eax ( old edx )


; int32 Atomic_or( vint32 * value, int32 bits )
FUNCTION Atomic_Or
	mov		edx, [esp + 4]				; edx = value
	mov		ecx, [esp + 8]				; ecx = bits
	mov		eax, edx					; eax = *edx
	or		ecx, eax					; ecx = ecx | eax
	lock
	cmpxchg	[edx], ecx					; if( eax == *edx ) *edx = ecx
										; loop if the value was changed by another cpu
	jnz		.begin						; else goto .begin
	ret									; return eax ( old edx )


; int32 Atomic_Get( vint32 * value )
FUNCTION Atomic_Get
	mov		edx, [esp + 4]				; edx = value
	mov		eax, [edx]					; eax = *edx
	mov		ecx, eax					; ecx = eax
	lock
	cmpxchg	[edx], ecx					; if( eax == *edx ) *edx = ecx
										; loop if the value was changed by another cpu
	jnz		.begin						; else goto .begin
	ret									; return eax ( edx )


; int32 Atomic_Set( vint32 * value, int32 newValue )
FUNCTION Atomic_Set
	mov		edx, [esp + 4]				; edx = value
	mov		eax, [esp + 8]				; eax = newValue
	lock
	xchg	[edx], eax					; *edx = eax
	ret									; return eax ( old edx )


; int32 Atomic_TestAndSet( vint32 * value, int32 test, int32 set ) 
FUNCTION Atomic_TestAndSet
	mov		edx, [esp + 4]				; edx = value
	mov		eax, [esp + 8]				; eax = test
	mov		ecx, [esp + 12]				; ecx = set
	lock
	cmpxchg	[edx], ecx					; if( eax == *edx ) *edx = ecx
										; loop if the value was changed by another cpu
	jnz		.begin						; else goto .begin
	ret


; int32 Atomic_Inc( vint32 * value )
FUNCTION Atomic_Inc
	mov		eax, [esp + 4]				; eax = value
	lock
	inc		dword [eax]					; *eax++
	ret									; return eax


; int32 Atomic_Dec( vint32 * value )
FUNCTION Atomic_Dec
	mov		eax, [esp + 4]				; eax = value
	lock
	dec		dword [eax]					; *eax--
	ret									; return eax


